package com.lnsoft.dqfs.test;

import com.lnsoft.dqfs.Application;
import com.lnsoft.dqfs.server.DqfsChannelInitializer;
import com.lnsoft.dqfs.server.dao.DqfsDao;
import com.lnsoft.dqfs.server.dao.Yc;
import com.lnsoft.dqfs.server.util.MessageUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 数据手动入库
 * 执行之前需要先修改下配置文件中连接数据的参数：（不然程序执行的时候，由于单个写入时间太长，容易导致超时错误）
 *      maxActive: 30
 *      maxWait: 180000
 */
//@Slf4j
public class DataDb_handwork2 {
    private static final Logger logger = LoggerFactory.getLogger(DataDb_handwork2.class);

    //  初始化线程池
    private static final ExecutorService pools = Executors.newFixedThreadPool(20);
    //  记录写文件到数据库的成功文件个数
    private static int fileTotal = 0;

    public static void main(String[] args) {
        //  初始化应用上下文
        ApplicationContext context = SpringApplication.run(Application.class, args);
        //  获取初始化好的数据库bean
        DqfsDao dqfsDao = context.getBean(DqfsDao.class);

//        String fileName = "C:\\Users\\Administrator\\.m2\\repository\\com\\lnsoft\\dqfs\\dqfs-server\\1.0\\4136_02019-3-11-5-36";
//        writeFile2DB(fileName,context);
        //  数据文件的所在的目录
//        String path = "D:\\工作相关（勿删）--贾来军\\201910\\20191018\\back-data";
        String path = "D:\\zhuzhan20191105\\data_upload_20191227";
        //  获取目录下的所有的文件
        File[] files = listFiles(path,dqfsDao);

        DataDb_handwork2 dataDb_handwork = new DataDb_handwork2();
        //  循环读取文件并写入数据库
        for (File file : files) {
//            writeFile2DB(file,dqfsDao);
            dataDb_handwork.execute(file,dqfsDao);
        }

    }

    //  获取目录下的所有文件
    public static File[] listFiles(String path,DqfsDao dqfsDao) {
        File dir = new File(path);
        File[] files = dir.listFiles();
        Integer index = 0;
        for (File file : files) {
        	logger.info("index:{}",index++);
        	logger.info("读取到的文件名称:{}", file.getName());
            Integer clientName = Integer.valueOf(file.getName().substring(0, 4));
            logger.info("终端号:{}",clientName);
            String clientId = dqfsDao.getIacmId(clientName, 2504);
            logger.info("终端ID:{}",clientId);
        }
        return files;
    }

    //  根据文件路径全名和应用上下文，将数据写入到数据库中
    public void writeFile2DB(File file,DqfsDao dqfsDao) {
        System.out.println("开始写入数据...");
        //  检查文件是否是具有完整遥测数据的文件
//        if (file.length() != 43201) {
//            System.out.println("数据不完整...");
//            return;
//        }

        List<Yc> list = null;
        RandomAccessFile randomAccessFile = null;
        try {
            //  包装打开的文件
            randomAccessFile = new RandomAccessFile(file, "rw");
            long len = randomAccessFile.length();
            logger.info("文件长度:{}", len);
            byte[] bytes = new byte[(int)len];
            int rd = randomAccessFile.read(bytes);
            logger.info("文件读取出的长度:{}", rd);
            ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes);


            while (byteBuf.isReadable()) {
                int index = byteBuf.bytesBefore((byte) 10);
                //  检查换行符字节位置
                logger.info("index of lf:{}", index);
                if (index < 0) {
                    break;
                }
                byte[] bytes1 = new byte[index];
                byteBuf.readBytes(bytes1);
                String lineStr = new String(bytes1);
                if (!lineStr.startsWith("16")) {
                	logger.info("行数据:{}", lineStr);
                }
                byteBuf.readByte();
            }

            list = new ArrayList<>(200);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            //  记录读取的行号
            int lineIndex = 0;
            while (true) {
                String line = randomAccessFile.readLine();
                //  行号自增
                lineIndex += 1;
                //  筛选哪些行的数据；此处是筛选135行以后的数据;正常情况下一个文件含有144行（条）数据;
//                if (lineIndex <= 135) {
//                    continue;
//                }
                //  检查行数据开头是否是真正的开头
                if (line == null || !line.startsWith("16")) {
                    break;
                }
                logger.info(line);
                logger.info("改行数据字节长度:{}",line.length());
                line = line.replace("\n", "").trim();

                if (line.lastIndexOf("16,2") > 1) {
                    line = line.substring(line.lastIndexOf("16,2"));
                }

                String[] datas = line.split(",");

                //  检查数据完整性，一组数据应该是34个字段
                if (datas.length != 34) {
                    continue;
                }
                
                Yc yc = new Yc();
            	yc.setCjsj(sdf.format(sdf2.parse(datas[1])));
            	yc.setTyndy(MessageUtil.upNanVal(datas[3].trim()));
            	yc.setDcdy(MessageUtil.upNanVal(datas[5].trim()));
            	yc.setJxwd(MessageUtil.upNanVal(datas[7].trim()));
            	yc.setJxsd(MessageUtil.upNanVal(datas[9].trim()));
            	yc.setGprs(MessageUtil.upNanVal(datas[11].trim()));
            	yc.setHjwd(MessageUtil.upNanVal(datas[13].trim()));
            	yc.setHjsd(MessageUtil.upNanVal(datas[15].trim()));
            	yc.setSond(MessageUtil.upNanVal(datas[17].trim()));
            	yc.setYf(MessageUtil.upNanVal(datas[19].trim()));
            	yc.setBy1(MessageUtil.upNanVal(datas[21].trim()));
            	yc.setBy2(MessageUtil.upNanVal(datas[23].trim()));
            	yc.setBy3(MessageUtil.upNanVal(datas[25].trim()));
            	yc.setZndl(MessageUtil.upNanVal(datas[27].trim()));
            	yc.setCudl(MessageUtil.upNanVal(datas[29].trim()));
            	yc.setAldl(MessageUtil.upNanVal(datas[31].trim()));
            	yc.setFedl(MessageUtil.upNanVal(datas[33].trim()));

                //  构造结构化的、将要写入数据库的数据
                list.add(yc);
            }



        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
//        //  测试：不把数据写入数据库
//        if (true) {
//            return;
//        }
        //  记录开始写入的时间
        long time = System.currentTimeMillis();
        if(list == null){
            final List<Yc> ycList = list;
            logger.info("文件名:{}",file.getName());
            Integer clientName = Integer.valueOf(file.getName().substring(0, 4));
            logger.info("终端号:{}",clientName);
            String clientId = dqfsDao.getIacmId(clientName, 2504);
            logger.info("终端ID:{}",clientId);
            //  执行写入
            dqfsDao.saveYcList(clientName, 2504, clientId, ycList);
            //  更新在线时间
            dqfsDao.updateIacmDownTime(clientId);

        }
        //  打印该次写入所用时间
        System.out.println(" 耗时:"+(System.currentTimeMillis()-time));
        //  打印已经成功写入的文件总数
        logger.info("写入数据库的文件总数:{}",++ fileTotal);

        return;
    }

    //  实现线程池的run方法
    public void execute(File file, DqfsDao dqfsDao) {
        pools.execute(new Runnable() {
            @Override
            public void run() {
                writeFile2DB(file,dqfsDao);
            }
        });
    }
}
